package com.code2roc.fastface.config;

import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.support.http.StatViewServlet;
import com.baomidou.mybatisplus.core.MybatisConfiguration;
import com.code2roc.fastface.db.MasterJdbcTemplate;
import com.code2roc.fastface.db.PackagesSqlSessionFactoryBean;
import org.apache.ibatis.session.SqlSessionFactory;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.sqlite.SQLiteConfig;
import org.sqlite.SQLiteOpenMode;

import javax.sql.DataSource;
import java.io.File;
import java.io.IOException;
import java.sql.SQLException;

@Configuration
public class DataSourceConfig {
    @Value("${datasource.master.driverClassName}")
    private String driverClassName;
    @Value("${datasource.master.url}")
    private String dbUrl;
    @Value("${datasource.master.username}")
    private String username;
    @Value("${datasource.master.password}")
    private String password;

    @Bean
    @Primary
    @Qualifier("masterDataSource")
    public DataSource masterDataSource() {
        DruidDataSource datasource = new DruidDataSource();
        if(driverClassName.equals("com.mysql.cj.jdbc.Driver")){
            if(!dbUrl.contains("useOldAliasMetadataBehavior")){
                dbUrl += "&useOldAliasMetadataBehavior=true";
            }
            if(!dbUrl.contains("useAffectedRows")){
                dbUrl += "&useAffectedRows=true";
            }
        }
        if(driverClassName.equals("org.sqlite.JDBC")){
            initSqliteFile(dbUrl.replace("jdbc:sqlite:",""));
            SQLiteConfig config= new SQLiteConfig();
            config.setOpenMode(SQLiteOpenMode.OPEN_URI);
            config.setOpenMode(SQLiteOpenMode.READWRITE);
            config.setOpenMode(SQLiteOpenMode.SHAREDCACHE);
            config.setOpenMode(SQLiteOpenMode.NOMUTEX);
            datasource.addConnectionProperty(SQLiteConfig.Pragma.OPEN_MODE.pragmaName, String.valueOf(config.getOpenModeFlags()));
            datasource.addConnectionProperty(SQLiteConfig.Pragma.JOURNAL_MODE.pragmaName, SQLiteConfig.JournalMode.WAL.toString() );
        }
        datasource.setUrl(this.dbUrl);
        datasource.setUsername(username);
        datasource.setPassword(password);
        datasource.setDriverClassName(driverClassName);
        //configuration
        datasource.setInitialSize(1);
        datasource.setMinIdle(3);
        datasource.setMaxActive(20);
        datasource.setMaxWait(60000);
        datasource.setTimeBetweenEvictionRunsMillis(60000);
        datasource.setMinEvictableIdleTimeMillis(60000);
        datasource.setValidationQuery("select 'x'");
        datasource.setTestWhileIdle(true);
        datasource.setTestOnBorrow(false);
        datasource.setTestOnReturn(false);
        datasource.setMaxPoolPreparedStatementPerConnectionSize(20);
        if(driverClassName.equals("org.sqlite.JDBC")){
            datasource.setPoolPreparedStatements(false);
        }else{
            datasource.setPoolPreparedStatements(true);
        }
        datasource.setLogAbandoned(false); //移除泄露连接发生是是否记录日志

        try {
            if(!driverClassName.equals("org.sqlite.JDBC")){
                datasource.setFilters("stat,slf4j");
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        datasource.setConnectionProperties("druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000");//connectionProperties);

        return datasource;
    }

    public static void initSqliteFile(String filePath){
        File file = new File(filePath);

        File dir = file.getParentFile();
        if(!dir.exists()){
            dir.mkdirs();
        }

        if(!file.exists()){
            try {
                file.createNewFile();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    @Primary
    @Bean("masterTransactionManager")
    public DataSourceTransactionManager MasterTransactionManager() {
        return new DataSourceTransactionManager(masterDataSource());
    }

    @Bean
    public ServletRegistrationBean druidServlet() {
        ServletRegistrationBean reg = new ServletRegistrationBean();
        reg.setServlet(new StatViewServlet());
        reg.addUrlMappings("/druid/*");
        reg.addInitParameter("allow", ""); //白名单
        reg.addInitParameter("loginUsername", "admin123");
        reg.addInitParameter("loginPassword", "abcd@1234");
        return reg;
    }

    @Bean
    public SqlSessionFactory sqlSessionFactory() throws Exception {
        final PackagesSqlSessionFactoryBean sessionFactory = new PackagesSqlSessionFactoryBean();
        sessionFactory.setDataSource(masterDataSource());
        //关闭驼峰转换，防止带下划线的字段无法映射
        sessionFactory.getObject().getConfiguration().setMapUnderscoreToCamelCase(false);
        MybatisConfiguration mybatisConfiguration =  sessionFactory.getConfiguration();
        if(mybatisConfiguration==null){
            mybatisConfiguration = new MybatisConfiguration();
        }
        sessionFactory.setConfiguration(mybatisConfiguration);
        return sessionFactory.getObject();
    }

    @Bean
    public MasterJdbcTemplate jdbcTemplate(){
        MasterJdbcTemplate jdbcTemplate = null;
        try{
            jdbcTemplate = new MasterJdbcTemplate(masterDataSource());
        }catch (Exception e){
            e.printStackTrace();
        }
        return jdbcTemplate;
    }
}
